<template>
  <!-- Cascader 级联组件，支持 v-model:value 双向绑定，支持远程 options -->
  <a-cascader v-bind="$attrs" v-model:value="innerValue" :options="finalOptions" :loading="loading" />
</template>

<script setup lang="ts">
import { ref, watch, onMounted, computed } from 'vue'

interface Props {
  value?: any // 当前绑定的值（v-model）
  api?: (_params?: any) => Promise<any> // 获取 options 的接口函数
  params?: Record<string, any> // 传给 API 的参数对象
  options?: any[] // 静态选项数据，优先级高于 api 返回
  resultField?: string // 结果字段路径（当 API 返回对象而非数组）
  labelField?: string // label 显示字段，默认 'label'
  valueField?: string // value 对应字段，默认 'value'
  childrenField?: string // 子节点字段名，默认 'children'
  immediate?: boolean // 是否组件挂载后立即请求，默认 true
}

// 设置默认 props
const props = withDefaults(defineProps<Props>(), {
  options: () => [],
  labelField: 'label',
  valueField: 'value',
  childrenField: 'children',
  immediate: true
})

// v-model 事件发射器
const emit = defineEmits(['update:value'])

// loading 状态
const loading = ref(false)

// 本地绑定值，用于 v-model:value 控制
const innerValue = ref(props.value)

// 动态远程 options
const dynamicOptions = ref<any[]>([])

/**
 * 计算最终 options 来源：
 * - 若 props.options 有数据，则优先使用本地传入 options
 * - 否则使用 api 拉取的数据
 */
const finalOptions = computed(() => {
  return props.options?.length ? props.options : dynamicOptions.value
})

/**
 * 异步加载 options 数据
 */
const fetchData = async () => {
  if (!props.api || props.options?.length) return // 若已有 options 或未提供 api，则跳过
  loading.value = true
  try {
    const res = await props.api(props.params)
    const list = props.resultField ? res[props.resultField] || [] : res
    dynamicOptions.value = Array.isArray(list) ? list : []
  } catch (err) {
    console.error('ApiCascader fetch error:', err)
  } finally {
    loading.value = false
  }
}

/**
 * 同步外部 v-model 的值到组件内部值
 */
watch(
  () => props.value,
  (val) => (innerValue.value = val)
)

/**
 * 当组件内部值变化时，发射 v-model 更新事件
 */
watch(innerValue, (val) => emit('update:value', val))

/**
 * 若传入的参数 props.params 发生变化，则重新请求数据
 */
watch(() => props.params, fetchData, { deep: true })

/**
 * 组件挂载后，根据 immediate 控制是否立即加载数据
 */
onMounted(() => {
  if (props.immediate && !props.options?.length) {
    fetchData()
  }
})
</script>
